package cossts;

import com.alibaba.fastjson.JSONObject;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.TransferManagerConfiguration;
import com.qcloud.cos.transfer.Upload;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * cossts
 *
 * @description:
 * @author: yechen
 * @email: wangqingfeng@wxyundian.com
 * @date: 2020年10月08日 15:44
 */
@Component
@Slf4j
public class CosCaller {
    //    private static String type = "COS";
    private static String bucket = "businessschool-h5-1259007136";
    private static String region = "ap-shanghai";
    private static String secretId = "AKIDNfomXLJpMlS4VluyQk18B3jFyviVrdpx";
    private static String secretKey = "7Plw78zfAUn02wjQ4ayhHiyKl152gHhR";
    //    private static String endPoint = "mps.tencentcloudapi.com";
    private static String cdnPath = "https://cdn-school.jikemofang.com";
//    private static String domain = "https://businessschool-h5-1259007136.cos.ap-shanghai.myqcloud.com";

    private static Map<String, String> fileExtensionContentTypeMap = new HashMap<>();

    static {
        fileExtensionContentTypeMap.put(".bmp", "image/bmp");
        fileExtensionContentTypeMap.put(".jpg", "image/jpg");
        fileExtensionContentTypeMap.put(".gif", "image/gif");
        fileExtensionContentTypeMap.put(".jpeg", "image/jpeg");
        fileExtensionContentTypeMap.put(".png", "image/png");
        fileExtensionContentTypeMap.put(".html", "text/html");
        fileExtensionContentTypeMap.put(".txt", "text/plain");
        fileExtensionContentTypeMap.put(".vsd", "application/vnd.visio");
        fileExtensionContentTypeMap.put(".ppt", "application/vnd.ms-powerpoint");
        fileExtensionContentTypeMap.put(".doc", "application/msword");
        fileExtensionContentTypeMap.put(".xml", "text/xml");
        fileExtensionContentTypeMap.put(".mp4", "video/mp4");
        fileExtensionContentTypeMap.put(".zip", "application/octet-stream");
        fileExtensionContentTypeMap.put(".xls", "application/octet-stream");
        fileExtensionContentTypeMap.put(".xlsx", "application/octet-stream");
    }

    /**
     * 初始化CosClient相关配置， appid、accessKey、secretKey、region
     *
     * @return
     */
    public static COSClient getCosClient() {
        // 1 初始化用户身份信息(secretId, secretKey)
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
        // 2 设置bucket的区域, COS地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        // clientConfig中包含了设置region, https(默认http), 超时, 代理等set方法, 使用可参见源码或者接口文档FAQ中说明
        ClientConfig clientConfig = new ClientConfig(new Region(region));
        // 3 生成cos客户端
        COSClient cosClient = new COSClient(cred, clientConfig);
        return cosClient;
    }

    public static TransferManager getTransferManager() {
        COSClient cosClient = getCosClient();
        // 对于使用公网传输且网络带宽质量不高的情况，建议减小该值，避免因网速过慢，造成请求超时。
        ExecutorService threadPool = Executors.newFixedThreadPool(8);
        // 传入一个 threadpool, 若不传入线程池，默认 TransferManager 中会生成一个单线程的线程池。
        TransferManager transferManager = new TransferManager(cosClient, threadPool);
        // 设置高级接口的分块上传阈值和分块大小为10MB
        TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
        transferManagerConfiguration.setMultipartUploadThreshold(1024 * 1024 * 1024);
        transferManagerConfiguration.setMinimumUploadPartSize(1024 * 1024 * 1024);
        transferManager.setConfiguration(transferManagerConfiguration);
        return transferManager;
    }

    public static String uploadByFile(File file, String originalUrl, String filePath, String newFileName) {
        COSClient cosclient = getCosClient();
        try {
            // 指定要上传到 COS 上的路径
            String key = "/" + filePath + "/" + newFileName;

            FileInputStream fileInputStream = new FileInputStream(file);
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(fileInputStream.available());
            metadata.setContentEncoding("utf-8");
            log.info("contentType={}", getContentType(originalUrl));
            metadata.setContentType(getContentType(originalUrl));

            PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, fileInputStream, metadata);
            PutObjectResult result = cosclient.putObject(putObjectRequest);
            log.info("<<<<cos返回结果 resp:{}", JSONObject.toJSONString(result));
            log.info("<<<<cos返回结果 url:{}", cdnPath + putObjectRequest.getKey());
        } catch (Exception e) {
            log.error("上传cos服务器异常.{}  e:{}", e.getMessage(), e);
        } finally {
            cosclient.shutdown();
        }
        return null;
    }

    public static String uploadByStream(InputStream inputStream, String originalUrl, String filePath, String newFileName) {
        COSClient cosclient = getCosClient();
        try {
            // 指定要上传到 COS 上的路径
            String key = "/" + filePath + "/" + newFileName;

            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(inputStream.available());
            metadata.setContentEncoding("utf-8");
            log.info("contentType={}", getContentType(originalUrl));
            metadata.setContentType(getContentType(originalUrl));

            PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, inputStream, metadata);
            PutObjectResult result = cosclient.putObject(putObjectRequest);
            log.info("<<<<cos返回结果 resp:{}", JSONObject.toJSONString(result));
            log.info("<<<<cos返回结果 url:{}", cdnPath + key);
        } catch (Exception e) {
            log.error("上传cos服务器异常.{}  e:{}", e.getMessage(), e);
        } finally {
            cosclient.shutdown();
        }
        return null;
    }

    public static String uploadByManager(File file, String vodCutVideoUrl, String filePath, String newFileName) {
        TransferManager transferManager = getTransferManager();
        // 指定要上传到 COS 上的路径
        String key = "/" + filePath + "/" + newFileName;
        try {
            file = getFile(vodCutVideoUrl);
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, file);
            // 本地文件上传
            Upload upload = transferManager.upload(putObjectRequest);
            // 等待传输结束（如果想同步的等待上传结束，则调用 waitForCompletion）
            upload.waitForCompletion();
            log.info("<<<<cos返回结果 url:{}", cdnPath + key);
            return cdnPath + key;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (file != null) {
                file.deleteOnExit();
            }
            transferManager.shutdownNow();
        }
        return null;
    }

    /**
     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
     *
     * @param fileName 文件名
     * @return: 文件的contentType
     * @auther: yechen
     * @Email: wangqingfeng@wxyundian.com
     * @date: 2018/10/19 0019 14:17
     */
    private static String getContentType(String fileName) {
        String fileExtension = fileName.substring(fileName.lastIndexOf("."));
        String contentTypeStr = fileExtensionContentTypeMap.get(fileExtension);
        if (StringUtils.isBlank(contentTypeStr)) {
            log.warn("上传OSS的类型不存在.");
            return "text/html";
        }
        return contentTypeStr;
    }

    /***
     * 获取网址链接，得到数据流
     *
     * @param uri
     * @return
     */
    public static InputStream getConnect(String uri) {
        long start = System.currentTimeMillis();
        BufferedInputStream bis = null;
        ByteArrayInputStream inputStream = null;
        try {
            //获取URL
            URL myUrl = new URL(uri);
            //开启链接
            URLConnection conn = myUrl.openConnection();
            //连接链接
            conn.connect();
            //获得链接数据流
            InputStream is = conn.getInputStream();

            bis = new BufferedInputStream(is);
            byte[] arr = new byte[4096];
            int len;

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            while ((len = bis.read(arr)) != -1) {
                bos.write(arr, 0, len);
            }
            byte[] bytes2 = bos.toByteArray();
            inputStream = new ByteArrayInputStream(bytes2);
        } catch (Exception e) {
            log.error("e={}", e);
        }
        log.info("远程地址转化为inputStream，总消耗{}ms", System.currentTimeMillis() - start);
        return inputStream;
    }

    private static File getFile(String url) throws Exception {
        long start = System.currentTimeMillis();
        File file = null;
        URL urlfile;
        InputStream inStream = null;
        OutputStream os = null;
        try {
            file = File.createTempFile("temp", null);
            //下载
            urlfile = new URL(url);
            inStream = urlfile.openStream();
            os = new FileOutputStream(file);

            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            log.error("e={}", e);
        } finally {
            try {
                if (null != os) {
                    os.close();
                }
                if (null != inStream) {
                    inStream.close();
                }

            } catch (Exception e) {
                log.error("e={}", e);
            }
        }
        log.info("远程地址转化为file，总消耗{}ms", System.currentTimeMillis() - start);
        return file;
    }

    public static String upload(String originalUrl, String vodCutVideoUrl, String newFileName) {
        File file = null;
        try {
            file = getFile(vodCutVideoUrl);
            String s = uploadByManager(file, vodCutVideoUrl, "video_short", newFileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (file != null) {
                file.deleteOnExit();
            }
        }
        return null;
    }

    public static void main(String[] args) {
        String originalUrl = "xxxxa.MP4";
        String vodCutVideoUrl = "http://1259097831.vod2.myqcloud.com/61de3e8fvodcq1259097831/e1bf61465285890808511083505/playlist.f5.mp4";

        String oldName = originalUrl.substring(0, originalUrl.indexOf("."));
        String eName = vodCutVideoUrl.substring(vodCutVideoUrl.lastIndexOf("."));
        String newFileName = oldName + "-" + "0.0x300.0" + eName;

        long start = System.currentTimeMillis();
        upload(originalUrl, vodCutVideoUrl, newFileName);
        log.info("<<<<<<<<<<上传cos，共消耗{} ms", System.currentTimeMillis() - start);
//        InputStream inputStream = null;
//        try {
//            inputStream = getConnect(vodCutVideoUrl);
//            long start = System.currentTimeMillis();
//            String s = uploadByStream(inputStream, vodCutVideoUrl, "video_short", newFileName);
//            log.info("<<<<<<<<<<上传cos，共消耗{} ms", System.currentTimeMillis() - start);
//        } catch (Exception e) {
//            log.error("<<<<上传cos失败，e={}", e);
//        } finally {
//            if (inputStream != null) {
//                //这里对文件进行操作
//                try {
//                    inputStream.close();
//                } catch (IOException e) {
//                    log.error("e={}", e);
//                }
//            }
//        }
    }
}
